package com.scott.classicthreadmodal.demo2.storage.delegate;

import com.scott.classicthreadmodal.demo2.storage.IStorage;
import com.scott.classicthreadmodal.Product;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * 仓库
 */
public class StorageBlockingQueue implements IStorage {

    /**
     * 最大数量
     */
    private final int MAX_SIZE = 10;

    /**
     * 产品列表
     */
    private BlockingQueue<Product> products = new LinkedBlockingDeque<>(10);

    /**
     * 生产产品
     *
     * @param num 数量
     * @throws InterruptedException 异常
     */
    public void produce(int num, String producerName) throws InterruptedException {
        if (products.size() == MAX_SIZE) {
            System.out.println(Thread.currentThread().getName()+":【" + producerName + "】【库存量】:" + MAX_SIZE + " 暂时不能执行生产任务!");
        }
        for (int i = 0; i <= num; i++) {
            Product product = new Product((int) (Math.random() * 100));
            products.put(product);
            System.out.println(Thread.currentThread().getName()+":【" + producerName + "】新生产产品：" + product.getId() + "【现仓储量为】:" + products.size());
        }
    }

    /**
     * 消费产品
     *
     * @return Product 产品
     * @throws InterruptedException 异常
     */
    public List<Product> consume(int num, String consumerName) throws InterruptedException {
        // 如果仓库存储量不足
        if (products.size() - num <= 0) {
            System.out.println(Thread.currentThread().getName()+":【" + consumerName + "】【购买数】:" + num + "，【库存量】:" + products.size() + " 不足，暂时不能执行消费任务!");
        }

        List<Product> result = new ArrayList<>();

        // 消费条件满足情况下，消费num个产品
        for (int i = 1; i <= num; ++i) {
            try {
                // 消费产品，自动阻塞
                result.add(products.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


        return result;
    }

    @Override
    public int getStock() {
        return products.size();
    }
}
